/*
 * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package com.jieshao.script

import com.jieshao.rule.ScriptContext
import com.jieshao.service.LineShareRuntime
import kotlinx.coroutines.*
import javax.script.ScriptEngine
import javax.script.ScriptEngineManager

@OptIn(DelicateCoroutinesApi::class)
val coroutinePool = newFixedThreadPoolContext(4, "CoroutinePool")

fun preScript(scriptContext: ScriptContext? = null): String {
    var script = "import com.jieshao.rule.*\n"
    scriptContext?.let {
        script += """
                    var projectPath: String = "${scriptContext.projectPath}"
                    var origin: String = "${scriptContext.origin}"
                    var currentRevision: String = "${scriptContext.currentRevision}"
                    var isLocalFile: Boolean = ${scriptContext.isLocalFile}
                    var filePath: String = "${scriptContext.filePath}"
                    var lineSelection: Pair<Int, Int>? = ${scriptContext.lineSelection?.let { "${it.first} to ${it.second}" } ?: "null"}
                """.trimIndent()
    }
    return script
}

fun innerEval(block: (ScriptEngine) -> String): String {
    try {
        // 等待协程完成并获取结果
        return runBlocking {

            val scope = CoroutineScope(coroutinePool)

            val result = scope.async {
                // 通过反射设置协程的类加载器
                Thread.currentThread().contextClassLoader = LineShareRuntime::class.java.classLoader
                // 模拟一些工作
                val engine = ScriptEngineManager().getEngineByExtension("kts")
                block.invoke(engine)
            }
            result.await()
        }

    } catch (e: Exception) {
        return "" + e.message
    }
}

fun eval(scriptString: String, scriptContext: ScriptContext? = null): String {
    return innerEval { engine ->
        engine.eval(preScript(scriptContext))
        engine.eval(scriptString) as String
    }
}

fun evalString(scriptString: String, scriptContext: ScriptContext? = null): String {
    return eval(scriptString, scriptContext)
}

